package shape;

/**
 * @author Zach Turk
 * @author Ken "David" McClain
 */

import physics.*;
import main.SceneGraphNode;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;

public class Square extends PhysicsObject implements Polygon {
	/** Serial ID */
	private static final long serialVersionUID = -1065739299729571292L;

	private static final float[] VERTICES = {0, 0, 
											 1, 0, 
											 1, 1, 
											 0, 1};
	 
	private Vector2f[] vertexCache;
	private Vector2f[] normalCache;
	
	private class Renderable extends SceneGraphNode {
		/** Serial ID */
		private static final long serialVersionUID = 1487729264956116494L;

		public void renderGeometry(GLAutoDrawable drawable) {
			GL2 gl = drawable.getGL().getGL2();
			
			gl.glBegin(GL.GL_TRIANGLE_FAN);
			gl.glVertex2d(0, 0);
			for (int i = 0; i < VERTICES.length; i += 2) {
				gl.glColor3f(colorRed + (float) i / 20, colorGreen + (float) i / 20, colorBlue + (float)i / 20);
				gl.glVertex2f(VERTICES[i], VERTICES[i+1]);
			}
			gl.glEnd();
		}
	}

	public Square(float size) {
		this(size, (float)Math.random(), (float)Math.random(), (float)Math.random());
	}
	
	public Square(float size, float red, float green, float blue) {
		centerOfMass.x = centerOfMass.y = size / 2;
		inverseMomentOfInertia = 1 / (float)(Math.pow(size, 4) / 12);
		renderable = new Renderable();
		renderable.scale = size;
		renderable.CoMX = centerOfMass.x;
		renderable.CoMY = centerOfMass.y;
		this.renderable.colorRed = red;
		this.renderable.colorBlue = blue;
		this.renderable.colorGreen = green;
	}
	
	public void setSize(float size) {
		centerOfMass.x = centerOfMass.y = size / 2;
		inverseMomentOfInertia = 1 / (float)(Math.pow(size, 4) / 12);
		renderable.scale = size;
		renderable.CoMX = centerOfMass.x;
		renderable.CoMY = centerOfMass.y;
	}
	
	public void clearCaches() {
		vertexCache = null;
		normalCache = null;
	}

	public Vector2f[] getVertices() {
		if (vertexCache == null) {
			vertexCache = new Vector2f[VERTICES.length / 2];
			Vector2f tmp = new Vector2f();
			for (int i = 0; i < VERTICES.length; i += 2) {
				tmp.x = VERTICES[i] * renderable.scale;
				tmp.y = VERTICES[i+1] * renderable.scale;
				tmp.sumScale(centerOfMass, -1);
				vertexCache[i/2] = new Vector2f();
				vertexCache[i/2].x = (float)(Math.cos(orientation) * tmp.x - Math.sin(orientation) * tmp.y);
				vertexCache[i/2].y = (float)(Math.sin(orientation) * tmp.x + Math.cos(orientation) * tmp.y);
				vertexCache[i/2].sum(centerOfMass);
				vertexCache[i/2].sum(position);
			}
		}
		return vertexCache;
	}
	
	public Vector2f[] getNormals() {
		if (normalCache == null) {
			Vector2f[] vertices = getVertices();
			normalCache = new Vector2f[vertices.length];

			for (int i = 0; i < vertices.length; i++) {
				normalCache[i] = new Vector2f(vertices[(i+1)%vertices.length]);
				normalCache[i].sumScale(vertices[i], -1);
				normalCache[i].normalize();
				float tmp = normalCache[i].x;
				normalCache[i].x = normalCache[i].y;
				normalCache[i].y = -tmp;
			}
		}
		return normalCache;
	}
}
